package org.nch.videoLauncher.util;

import java.net.URL;
import java.net.Authenticator;
import java.util.ArrayList;

/**
 * Derived from XMM (xmm.sourceforge.net), class net.sf.xmm.moviemanager.http.IMDB
 */
public class IMDB {

    /**
     * The imdb key for the movie.
     */
    private String _key = "";

    /**
     * The date of the movie
     */
    private String _date = "";

    /**
     * The dateof the movie.
     */
    private String _title = "";

    /**
     * Directed by.
     */
    private String _directedBy = "";

    /**
     * Written by.
     */
    private String _writtenBy = "";

    /**
     * Genre.
     */
    private String _genre = "";

    /**
     * The rating.
     */
    private String _rating = "";


    /**
     * The colour of the movie
     */
    private String _colour = "";

    /**
     * Also known as of the movie
     */
    private String _aka = "";

    /**
     * The country of the movie
     */
    private String _country = "";

    /**
     * The language of the movie
     */
    private String _language = "";

    /**
     * The Sound Mix of the movie
     */
    private String _mpaa = "";

    /**
     * The Sound Mix of the movie
     */
    private String _soundMix = "";

    /**
     * The Sound Mix of the movie
     */
    private String _runtime = "";

    /**
     * The Sound Mix of the movie
     */
    private String _certification = "";

    /**
     * The Sound Mix of the movie
     */
    private String _awards = "";

    /**
     * The plot.
     */
    private String _plot = "";

    /**
     * The cast.
     */
    private String _cast = "";

    /**
     * The cover url.
     */
    private String _coverURL = "";


    /**
     * The cover url.
     */
    private String _coverName = "";

    /**
     * Reding ok...
     */
    private boolean _coverOK = false;

    /* stores the last exception message */
    private static String exception;

    /**
     * The constructor. Initializes all vars (read from the net) for
     * the movie with key.
     */
    public IMDB(String key) throws Exception {

        _key = key;

        /* Gets the url... */
        URL url = makeURL("http://akas.imdb.com/title/tt" + key + "/");

        /* Saves the page data in a string buffer... */
        StringBuffer data = HttpUtil.readDataToStringBuffer(url);

        if (data == null) {
            throw new Exception("Invalid HTTP link");
        }

        parseData(data);
    }


    public IMDB(String key, StringBuffer data) throws Exception {

        _key = key;

        parseData(data);
    }


    private void parseData(StringBuffer data) throws Exception {

        int start = 0;
        int stop = 0;
        int end = 0;

        Object[] tmpArray;

        try {
            /* Processes the data... */

            /* Gets the title... */
            if ((start = data.indexOf("<div id=\"tn15title\">", start)) != -1 &&
                    (end = data.indexOf("</div>", start)) != -1) {

                tmpArray = HttpUtil.decodeHTMLtoArray(data.substring(start, end));

                _title = (String) tmpArray[0];

                if (_title.startsWith("The ")) {
                    _title = _title.substring(_title.indexOf(" ") + 1, _title.length()) + ", The";
                } else if ((_title.startsWith("A ") || _title.startsWith("An "))) {
                    _title = _title.substring(_title.indexOf(" ") + 1, _title.length()) + ", " + _title.substring(0, _title.indexOf(" "));
                }

                _date = (String) tmpArray[2];
            }

            /* Gets the cover url... */
            if ((start = data.indexOf("<div class=\"photo\">")) != -1 &&
                    (end = data.indexOf("</div>", start)) != -1) {

                if (data.substring(start, end).indexOf("Poster Not Submitted") == -1) {

                    if ((start = data.indexOf("src=\"", start) + 5) != 4 &&
                            (end = data.indexOf("\"", start)) != -1) {
                        _coverURL = HttpUtil.decodeHTML(data.substring(start, end));
                    }

                    start = _coverURL.lastIndexOf(".");

                    if (start != 0 && start != -1)
                        _coverName = _key + _coverURL.substring(start, _coverURL.length());
                }
            }

            start = 0;
            stop = 0;
            end = 0;
            /* Gets the rating... */
            if ((start = data.indexOf("User Rating:", start) + 12) != 11 &&
                    (end = data.indexOf("/10</b>", start)) != -1 &&
                    (start = data.indexOf("<b>", end - 9) + 3) != 2) {

                _rating = HttpUtil.decodeHTML(data.substring(start, end));
            }

            start = 0;
            stop = 0;
            end = 0;

            // Gets the directed by...
            String tmp = getClassInfo(data, "Director");
            tmp = tmp.substring(tmp.indexOf(":") + 1, tmp.length());

            ArrayList list = getLinkContentName(tmp);

            while (!list.isEmpty()) {
                if (!_directedBy.equals(""))
                    _directedBy += ", ";

                _directedBy += list.remove(0);
            }

            // Gets the written by...
            tmp = getClassInfo(data, "Writer");
            tmp = tmp.substring(tmp.indexOf(":") + 1, tmp.length());

            list = getLinkContentName(tmp);

            while (!list.isEmpty()) {
                if (!_writtenBy.equals(""))
                    _writtenBy += ", ";

                _writtenBy += list.remove(0);
            }

            _genre = getDecodedClassInfo(data, "Genre:");

            _genre = _genre.replaceAll("(more)$", "");

            _plot = getDecodedClassInfo(data, "Plot Outline:");

            _cast = getDecodedClassInfo(data, "class=\"cast\">");

            _cast = _cast.replaceAll(" \\.\\.\\.", ",");

            _aka = getDecodedClassInfo(data, "Also Known As:");

            _mpaa = getDecodedClassInfo(data, "<a href=\"/mpaa\">MPAA</a>:");

            _runtime = getDecodedClassInfo(data, "Runtime:");

            _country = getDecodedClassInfo(data, "Country:");

            _language = getDecodedClassInfo(data, "Language:");

            _colour = getDecodedClassInfo(data, "Color:");

            _soundMix = getDecodedClassInfo(data, "Sound Mix:");

            _certification = getDecodedClassInfo(data, "Certification:");

            _awards = getDecodedClassInfo(data, "Awards:");
            _awards = _awards.replaceAll("(more)$", "");

            /* Gets a bigger plot (if it exists...)
        /* Creates the url... */
            URL url = new URL("http://akas.imdb.com/title/tt" + _key + "/plotsummary");

            data = HttpUtil.readDataToStringBuffer(url);

            /* Processes the data... */
            start = 0;
            end = 0;

            if ((start = data.indexOf("class=\"plotpar\">", start) + 16) != 15 &&
                    (end = data.indexOf("</p>", start)) != -1) {
                _plot = HttpUtil.decodeHTML(data.substring(start, end));

                if (_plot.indexOf("Written by") != -1)
                    _plot = _plot.substring(0, _plot.indexOf("Written by"));
            }

            _plot = _plot.trim();
            _plot = _plot.replaceAll("(more)$", "");

        } catch (Exception e) {
            System.out.println(e.getMessage());
            ;
        }
    }

    /**
     * Gets the key.
     */
    public String getKey() {
        return _key;
    }

    /**
     * Gets the date.
     */
    public String getDate() {
        return _date;
    }

    /**
     * Gets the title.
     */
    public String getTitle() {
        return _title;
    }

    /**
     * Gets the durected by.
     */
    public String getDirectedBy() {
        return _directedBy;
    }

    /**
     * Gets the written by.
     */
    public String getWrittenBy() {
        return _writtenBy;
    }

    /**
     * Gets the genre.
     */
    public String getGenre() {
        return _genre;
    }

    /**
     * Gets the rating.
     */
    public String getRating() {
        return _rating;
    }

    /**
     * Gets the colour.
     */
    public String getColour() {
        return _colour;
    }

    /**
     * Gets the country.
     */
    public String getCountry() {
        return _country;
    }

    /**
     * Gets the language.
     */
    public String getLanguage() {
        return _language;
    }

    /**
     * Gets the plot.
     */
    public String getPlot() {
        return _plot;
    }

    /**
     * Gets the cast.
     */
    public String getCast() {
        return _cast;
    }

    /**
     * Gets the aka.
     */
    public String getAka() {
        return _aka;
    }

    /**
     * Gets the mpaa.
     */
    public String getMpaa() {
        return _mpaa;
    }

    /**
     * Gets the Sound Mix.
     */
    public String getSoundMix() {
        return _soundMix;
    }

    /**
     * Gets the Runtime.
     */
    public String getRuntime() {
        return _runtime;
    }

    /**
     * Gets the Certification.
     */
    public String getCertification() {
        return _certification;
    }

    /**
     * Gets the Awards.
     */
    public String getAwards() {
        return _awards;
    }


    /**
     * Gets the cover url.
     */
    public String getCoverName() {
        return _coverName;
    }

    /**
     * Gets the cover url.
     */
    public String getCoverURL() {
        return _coverURL;
    }

    /**
     * Gets the cover.
     */
    public byte[] getCover() {

        byte[] coverData = {-1};
        try {

            if (!_coverURL.equals("")) {

                URL url = new URL(_coverURL);
                coverData = HttpUtil.readDataToByteArray(url);

                _coverOK = true;
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
            ;
            _coverOK = false;
        }

        /* Returns the data... */
        return coverData;
    }

    /**
     * Returns true if the last cover reading went ok..
     */
    public boolean getCoverOK() {
        return _coverOK;
    }


    /**
     * Grabs the content of a class info containing the classname
     */
    protected static String getClassInfo(StringBuffer data, String className) {
        String tmp = "";


        int start = 0;
        int end = 0;
        boolean found = false;

        while ((start = data.indexOf("class=\"info\">", end)) != -1 &&             // removed "<div" to fix director lookup

                (end = data.indexOf("</div>", start)) != -1) {

            tmp = data.substring(start, end);

            if (tmp.indexOf(className) != -1) {

                start = tmp.indexOf(className) + className.length();
                tmp = tmp.substring(start, tmp.length());
                tmp = tmp.trim();
                break;
            }
            tmp = "";
        }
        return tmp;
    }


    /**
     * Grabs the content of a class info containing the classname
     * and cleans it up by removing html and paranthesis.
     */
    protected static String getDecodedClassInfo(StringBuffer data, String className) {
        String decoded = "";
        String tmp = "";

        try {
            int start = 0;
            int end = 0;
            boolean found = false;

            tmp = getClassInfo(data, className);

            end = tmp.indexOf("<a class=\"tn15more\"");

            if (end != -1) {
                tmp = tmp.substring(0, end);
            }

            if (className.equals("Also Known As:")) {
                decoded = decodeAka(tmp);
            } else if (className.equals("class=\"cast\">")) {
                decoded = decodeCast(tmp);
            } else
                decoded = HttpUtil.decodeHTML(tmp);

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        /* Returns the decoded string... */
        return decoded.trim();
    }


    /**
     * Decodes a html string and returns its unicode string.
     */
    protected static ArrayList getLinkContentName(String toDecode) {
        ArrayList decoded = new ArrayList();
        String tmp = "";

        try {
            int start = 0;
            int end = 0;

            while ((start = toDecode.indexOf("<a href=", start)) != -1) {

                start = toDecode.indexOf(">", start) + 1;
                end = toDecode.indexOf("</a>", start);

                tmp = toDecode.substring(start, end);
                decoded.add(HttpUtil.decodeHTML(tmp.trim()));
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        /* Returns the decoded string... */
        return decoded;
    }

    /**
     * Decodes a html string and returns its unicode string.
     */
    protected static String decodeAka(String toDecode) {
        String decoded = "";

        try {
            String[] akaTitles = toDecode.split("<br>");

            for (int i = 0; i < akaTitles.length; i++) {
                decoded += HttpUtil.decodeHTML(akaTitles[i]) + "\r\n";
            }

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        /* Returns the decoded string... */
        return decoded.trim();
    }


    /**
     * Decodes a html string and returns its unicode string.
     */
    protected static String decodeCast(String toDecode) {
        StringBuffer decoded = new StringBuffer();

        try {
            String[] castSplit = toDecode.split("<td class=\"hs\">");
            String[] tmp;

            for (int i = 0; i < castSplit.length; i++) {

                tmp = HttpUtil.decodeHTML(castSplit[i]).split(" \\.\\.\\.");

                if (tmp.length == 2) {
                    decoded.append(tmp[0].trim());
                    decoded.append(" (" + tmp[1].trim() + "), ");
                }
            }

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        /* Returns the decoded string... */
        return decoded.toString();
    }


    /* Creates the URL */
    protected static URL makeURL(String url) {

        URL urlData = null;

        try {
            urlData = new URL(url);
        }
        catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return urlData;
    }

    public static String getException() {
        return exception;
    }

    static void setException(String e) {
        exception = e;
    }
}

